Telegram Group & Telegram Channel
Принцип на все времена: Command-Query Separation

CQS очень простой принцип программирования, применение которого встречается на каждом шагу. Обычно его формулируют так: “задавая вопрос, не изменяй ответ”. Представьте что у вас есть функция, которая проверяет валидность объекта user.isValid(). По смыслу эта функция проверяет данные по каким-то правилам и возвращает true/false.

Может ли она что-то менять? Большинство скажет что это не логично и будет право. Она не должна ничего менять. На практике же, это происходит тут и там. В тех же Rails, вы легко встретите внутри модели колбек before_validation, в котором можно сделать любое изменение, которое сработает на вызов valid?. И этим часто пользуются, я был свидетелем, как в коде удалялись связи у пользователя. Но тоже самое встречается налево и направо у программистов во всех языках.

Однажды, когда я собесил человека на наставника в Хекслет, мы как-то по пути выяснили, что у них там в коде во время запроса каких-то опций, они удалялись из списка опций, мы обсудили этот момент, я чуть-чуть рассказал про CQS и разработчик мне ответил, что после разговора пойдет переписывать код :)

Почему это вообще важно? Тут можно сказать про принцип наименьшего удивления. Код, который меняет что-то на проверку/запрос данных, вводит в ступор всех кто с ним работает. Систему можно проектировать так чтобы этого не было и код делал ровно то, что он заявляет. Есть правда пара исключений, это отложенная инициализация, но снаружи она выгялядит всегда так, как будто изменения не было. И второе, это разного рода аналитика во время работы, например подсчет числа визитов при запросе страницы.

Кстати да, это правило распространяется на все вокруг. Именно поэтому в HTTP существует GET, который можно кешировать так как он сам не меняет данные (но данные могут поменяться по другим причинам), а POST всегда меняет, поэтому кеширование к нему не применяется.

Буквально недавно мы разговаривали с Тагиром и он поделился тем как в Java работает форматирование дат. Оказалось, что в Java есть объект SimpleDateFormat, и он непотокобезопасен. Почему? Потому что метод, который вроде бы просто форматирует дату в строку, на самом деле меняет внутреннее состояние объекта. И если два потока одновременно вызовут .format(…), то они могут получить некорректный результат. Это классический пример нарушения CQS: метод, выглядящий как query (просто возвращает значение), внезапно ведёт себя как command — вносит изменения.

В результате приходится либо каждый раз создавать новый SimpleDateFormat, либо оборачивать его в ThreadLocal, либо использовать DateTimeFormatter из более нового API, который как раз спроектирован с учётом CQS — он ничего не мутирует.

Такие детали, на первый взгляд мелочи, но на практике они и создают разницу между кодом, который легко читать и расширять, и кодом, в котором ты боишься вызвать метод, потому что не знаешь, что он там делает под капотом.

Но это что касается вопросов. А что насчет команд? Тут уже не так очевидно, почему если мы выполняем действие (`setSomething()`, doSomething(), то данные лучше не возвращать?

Во-первых, это снова вопрос читаемости и предсказуемости. Метод с названием deleteUser(id) должен просто удалить пользователя, а не возвращать его профиль. Когда действие возвращает что-то, разработчики начинают полагаться на это значение: передавать его дальше, использовать как флаг, делать выводы.

Во-вторых, это помогает отделить побочные эффекты от чистых вычислений. Когда метод возвращает что-то, возникает иллюзия, что это «безопасно» — можно просто вызвать и использовать результат. Но за кулисами может происходить что угодно: удаление из базы, отправка письма, пересчёт кэша. Такое поведение тяжело тестировать и отлаживать.

Это не значит, что действия никогда ничего не возвращают. Иногда они могут вернуть, например, true или false, чтобы явно показать успех или неудачу. Более того, в некоторых ситуациях невозможно соблюдать CQS, например, при открытии файла на запись (создается файловый дескриптор).

Ссылки: Телеграм | Youtube | VK


p.s. Признавайтесь, писали такой код?



tg-me.com/orgprog/309
Create:
Last Update:

Принцип на все времена: Command-Query Separation

CQS очень простой принцип программирования, применение которого встречается на каждом шагу. Обычно его формулируют так: “задавая вопрос, не изменяй ответ”. Представьте что у вас есть функция, которая проверяет валидность объекта user.isValid(). По смыслу эта функция проверяет данные по каким-то правилам и возвращает true/false.

Может ли она что-то менять? Большинство скажет что это не логично и будет право. Она не должна ничего менять. На практике же, это происходит тут и там. В тех же Rails, вы легко встретите внутри модели колбек before_validation, в котором можно сделать любое изменение, которое сработает на вызов valid?. И этим часто пользуются, я был свидетелем, как в коде удалялись связи у пользователя. Но тоже самое встречается налево и направо у программистов во всех языках.

Однажды, когда я собесил человека на наставника в Хекслет, мы как-то по пути выяснили, что у них там в коде во время запроса каких-то опций, они удалялись из списка опций, мы обсудили этот момент, я чуть-чуть рассказал про CQS и разработчик мне ответил, что после разговора пойдет переписывать код :)

Почему это вообще важно? Тут можно сказать про принцип наименьшего удивления. Код, который меняет что-то на проверку/запрос данных, вводит в ступор всех кто с ним работает. Систему можно проектировать так чтобы этого не было и код делал ровно то, что он заявляет. Есть правда пара исключений, это отложенная инициализация, но снаружи она выгялядит всегда так, как будто изменения не было. И второе, это разного рода аналитика во время работы, например подсчет числа визитов при запросе страницы.

Кстати да, это правило распространяется на все вокруг. Именно поэтому в HTTP существует GET, который можно кешировать так как он сам не меняет данные (но данные могут поменяться по другим причинам), а POST всегда меняет, поэтому кеширование к нему не применяется.

Буквально недавно мы разговаривали с Тагиром и он поделился тем как в Java работает форматирование дат. Оказалось, что в Java есть объект SimpleDateFormat, и он непотокобезопасен. Почему? Потому что метод, который вроде бы просто форматирует дату в строку, на самом деле меняет внутреннее состояние объекта. И если два потока одновременно вызовут .format(…), то они могут получить некорректный результат. Это классический пример нарушения CQS: метод, выглядящий как query (просто возвращает значение), внезапно ведёт себя как command — вносит изменения.

В результате приходится либо каждый раз создавать новый SimpleDateFormat, либо оборачивать его в ThreadLocal, либо использовать DateTimeFormatter из более нового API, который как раз спроектирован с учётом CQS — он ничего не мутирует.

Такие детали, на первый взгляд мелочи, но на практике они и создают разницу между кодом, который легко читать и расширять, и кодом, в котором ты боишься вызвать метод, потому что не знаешь, что он там делает под капотом.

Но это что касается вопросов. А что насчет команд? Тут уже не так очевидно, почему если мы выполняем действие (`setSomething()`, doSomething(), то данные лучше не возвращать?

Во-первых, это снова вопрос читаемости и предсказуемости. Метод с названием deleteUser(id) должен просто удалить пользователя, а не возвращать его профиль. Когда действие возвращает что-то, разработчики начинают полагаться на это значение: передавать его дальше, использовать как флаг, делать выводы.

Во-вторых, это помогает отделить побочные эффекты от чистых вычислений. Когда метод возвращает что-то, возникает иллюзия, что это «безопасно» — можно просто вызвать и использовать результат. Но за кулисами может происходить что угодно: удаление из базы, отправка письма, пересчёт кэша. Такое поведение тяжело тестировать и отлаживать.

Это не значит, что действия никогда ничего не возвращают. Иногда они могут вернуть, например, true или false, чтобы явно показать успех или неудачу. Более того, в некоторых ситуациях невозможно соблюдать CQS, например, при открытии файла на запись (создается файловый дескриптор).

Ссылки: Телеграм | Youtube | VK


p.s. Признавайтесь, писали такой код?

BY Организованное программирование | Кирилл Мокевнин




Share with your friend now:
tg-me.com/orgprog/309

View MORE
Open in Telegram


Организованное программирование | Кирилл Мокевнин Telegram | DID YOU KNOW?

Date: |

What is Secret Chats of Telegram

Secret Chats are one of the service’s additional security features; it allows messages to be sent with client-to-client encryption. This setup means that, unlike regular messages, these secret messages can only be accessed from the device’s that initiated and accepted the chat. Additionally, Telegram notes that secret chats leave no trace on the company’s services and offer a self-destruct timer.

The SSE was the first modern stock exchange to open in China, with trading commencing in 1990. It has now grown to become the largest stock exchange in Asia and the third-largest in the world by market capitalization, which stood at RMB 50.6 trillion (US$7.8 trillion) as of September 2021. Stocks (both A-shares and B-shares), bonds, funds, and derivatives are traded on the exchange. The SEE has two trading boards, the Main Board and the Science and Technology Innovation Board, the latter more commonly known as the STAR Market. The Main Board mainly hosts large, well-established Chinese companies and lists both A-shares and B-shares.

Организованное программирование | Кирилл Мокевнин from ms


Telegram Организованное программирование | Кирилл Мокевнин
FROM USA